package terra.managers;
 
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.newdawn.slick.Animation;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Sound;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.loading.LoadingList;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
 
public class ResourceManager {
 
	private static String SPRITE_SHEET_REF = "__SPRITE_SHEET_";
	public static boolean loaded = false;
	private static Map<String, Sound> soundMap;
	private static Map<String, Image> imageMap;
	private static Map<String, Animation> animationMap;
	private static Map<String, String> textMap;
	private static Map<String, String> pathMap;	
	public static void loadResources(InputStream is) {
		soundMap 	 = new HashMap<String, Sound>();
		imageMap 	 = new HashMap<String, Image>();
		animationMap = new HashMap<String, Animation>();
		textMap 	 = new HashMap<String, String>();
		pathMap 	 = new HashMap<String, String>();
		loadResources(is, false,false);
	}
 
	public static void loadResources(InputStream is, boolean deferred,boolean textOnly){
		DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = null;
		try {
			docBuilder = docBuilderFactory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		Document doc = null;
        try {
			doc = docBuilder.parse (is);
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
 
		// normalize text representation
        doc.getDocumentElement ().normalize ();
 
        NodeList listResources = doc.getElementsByTagName("resource");
 
        int totalResources = listResources.getLength();
 
        if(deferred){
        	LoadingList.setDeferredLoading(true);
        }
 
 
        for(int resourceIdx = 0; resourceIdx < totalResources; resourceIdx++){
 
        	Node resourceNode = listResources.item(resourceIdx);
 
        	if(resourceNode.getNodeType() == Node.ELEMENT_NODE){
        		Element resourceElement = (Element)resourceNode;
 
        		String type = resourceElement.getAttribute("type");
        		if (textOnly)
        		{
        			if(type.equals("text"))
        				addElementAsText(resourceElement);
        		}
        		else	
        		{
        		if(type.equals("image")){
        			addElementAsImage(resourceElement);
        		}else if(type.equals("sound")){
        			addElementAsSound(resourceElement);
        		}else if(type.equals("text")){
        			addElementAsText(resourceElement);
        		}else if(type.equals("font")){
 
        		}else if(type.equals("animation")){
        			addElementAsAnimation(resourceElement);
        		}else if(type.equals("sprite")){
        			addElementAsSprite(resourceElement);
        		}
        		
                loaded = true;
        		}
        	}
        }

	}
 
	private static void addElementAsSprite(Element resourceElement)
	{
		Image sheet = loadImage(resourceElement.getAttribute("id"), resourceElement.getTextContent());
    	int x  =  Integer.parseInt(resourceElement.getAttributes().getNamedItem("x").getNodeValue());
    	int y  =  Integer.parseInt(resourceElement.getAttributes().getNamedItem("y").getNodeValue());
    	int w  =  Integer.parseInt(resourceElement.getAttributes().getNamedItem("w").getNodeValue());
    	int h  =  Integer.parseInt(resourceElement.getAttributes().getNamedItem("h").getNodeValue());
    	Image img  = sheet.getSubImage(x, y, w, h);
    	imageMap.put(resourceElement.getAttribute("id"), img);
	}
	
	private static void addElementAsAnimation(Element resourceElement){
		try {
			loadAnimation(resourceElement.getAttribute("id"), resourceElement.getTextContent(), 
					Integer.valueOf(resourceElement.getAttribute("tw")),
					Integer.valueOf(resourceElement.getAttribute("th")),
					Integer.valueOf(resourceElement.getAttribute("duration")));
		} catch (NumberFormatException e) {

			e.printStackTrace();
		} catch (DOMException e) {

			e.printStackTrace();
		}
	}
 
	private static void loadAnimation(String id, String spriteSheetPath,
			int tw, int th, int duration){
		//if(spriteSheetPath == null || spriteSheetPath.length() == 0)
			
			SpriteSheet spr = new SpriteSheet(loadImage( SPRITE_SHEET_REF + id, spriteSheetPath), tw, th);
			 
			Animation animation = new Animation(spr, duration);
	 
		animationMap.put(id,animation);
	}
 
	public static final Animation getAnimation(String ID){
		return animationMap.get(ID);
	}
 
	private static void addElementAsText(Element resourceElement){
		loadText(resourceElement.getAttribute("id"), resourceElement.getTextContent());
	}
 
	public static String loadText(String id, String value){
		if(value == null)
			System.out.println("Text resource [" + id + "] has invalid value");
 
		textMap.put(id, value);
 
		return value;
	}
 
	public static String getText(String ID) {
		return textMap.get(ID);
	}
 
	private static void addElementAsSound(Element resourceElement){
		loadSound(resourceElement.getAttribute("id"), resourceElement.getTextContent());
	}
 
	public static Sound loadSound(String id, String path){
 
		Sound sound = null;
 
		try {
			sound = new Sound(path);
		} catch (SlickException e) {
			e.printStackTrace();
		}
 
		soundMap.put(id, sound);
 
		return sound;
	}
 
	public static final Sound getSound(String ID){
		return soundMap.get(ID);
	}
 
	 public static void addImage(Image image, String ID)
	 {
		 imageMap.put(ID, image);
	 }
	 
	private static final void addElementAsImage(Element resourceElement){
		loadImage(resourceElement.getAttribute("id"), resourceElement.getTextContent());
		pathMap.put(resourceElement.getAttribute("id"), resourceElement.getTextContent());
	}
 
	public static Image loadImage(String id, String path){
		Image image = null;
		try{
			image = new Image(path);
		} catch (Exception e) {
			e.printStackTrace();
		}
 
		
		imageMap.put(id, image);
 
		return image;
	}
 
	public static final Image getImage(String ID){
		Image img = imageMap.get(ID);
		if (img == null){
			System.out.println("getImage == null ID " + ID);
			img = imageMap.get("block_background");
		}
		return img;
	}

	public static String getPath(String image) {
		return pathMap.get(image);
	}
 
}